package com.letfox.finance.service.impl;

import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.SortedMap;
import java.util.TreeMap;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.letfox.common.util.DateUtil;
import com.letfox.finance.dao.AccountDao;
import com.letfox.finance.dao.AccountRlInoutDao;
import com.letfox.finance.dao.IncomeDetailDao;
import com.letfox.finance.enums.FINDelEnums;
import com.letfox.finance.enums.FINInWayEnums;
import com.letfox.finance.enums.FINInoutPayChannelEnums;
import com.letfox.finance.enums.FINInoutTypeEnums;
import com.letfox.finance.model.FINAccount;
import com.letfox.finance.model.FINAccountRlInout;
import com.letfox.finance.model.FINIncomeDetail;
import com.letfox.finance.service.WXPayService;
import com.letfox.finance.wxpay.util.PayForUtil;
import com.letfox.finance.wxpay.util.WeChatConfig;
import com.letfox.finance.wxpay.util.WeChatParams;
import com.letfox.finance.wxpay.util.WeixinPay;
import com.letfox.finance.wxpay.util.XMLUtil;
@Service
public class WXPayServiceImpl implements WXPayService {
	@Autowired
	private AccountDao accountcDao;
	@Autowired
	private AccountRlInoutDao accountRlInoutDao;
	@Autowired
	private IncomeDetailDao incomeDetailDao;
	
    public void pay(HttpServletResponse  response,WeChatParams weChatParams){
    	
    	try {
    	if(weChatParams.getUserId() != null && weChatParams.getBody() ==null && weChatParams.getTotal_fee() != null && weChatParams.getAccountId() != null && weChatParams.getOut_trade_no() !=null){
	    		String content = WeixinPay.getCodeUrl(weChatParams);
	    		WeixinPay.encodeQrcode(content, response);
	    	}else{
	    		weChatParams.setAttach(weChatParams.getUserId()+"_"+weChatParams.getAccountId()+"_"+weChatParams.getOut_trade_no());
	    		String resXml = "传入有空值，参数不正确。";
	    		BufferedOutputStream out = new BufferedOutputStream(  
                        response.getOutputStream());  
                out.write(resXml.getBytes());  
                out.flush();  
                out.close();
	    	}
			
		} catch (Exception e) {
			e.printStackTrace();
		}
    }
    
    /**
    * pc端微信支付之后的回调方法
    * @param request
    * @param response
    * @throws Exception
    */
    public void wechat_notify_url_pc(HttpServletRequest request,HttpServletResponse response) throws Exception{  
            
            //读取参数  
            InputStream inputStream ;  
            StringBuffer sb = new StringBuffer();  
            inputStream = request.getInputStream();  
            String s ;  
            BufferedReader in = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));  
            while ((s = in.readLine()) != null){  
                sb.append(s);  
            }  
            in.close();  
            inputStream.close();  
      
            //解析xml成map  
            Map<String, String> m = new HashMap<String, String>();  
            m = XMLUtil.doXMLParse(sb.toString());  
              
            //过滤空 设置 TreeMap  
            SortedMap<Object,Object> packageParams = new TreeMap<Object,Object>();        
            Iterator<String> it = m.keySet().iterator();  
            while (it.hasNext()) {  
                String parameter = it.next();  
                String parameterValue = m.get(parameter);  
                  
                String v = "";  
                if(null != parameterValue) {  
                    v = parameterValue.trim();  
                }  
                packageParams.put(parameter, v);  
            }  
            // 微信支付的API密钥  
            String key = WeChatConfig.APIKEY; // key  
      
            //lg.info("微信支付返回回来的参数："+packageParams);  
            //判断签名是否正确  
            if(PayForUtil.isTenpaySign("UTF-8", packageParams,key)) {  
                //------------------------------  
                //处理业务开始  
                //------------------------------  
                String resXml = "";  
                if("SUCCESS".equals((String)packageParams.get("result_code"))){  
                    // 这里是支付成功  
                //执行自己的业务逻辑开始
                String app_id = (String)packageParams.get("appid");
                    String mch_id = (String)packageParams.get("mch_id");  
                    String openid = (String)packageParams.get("openid"); 
                    String is_subscribe = (String)packageParams.get("is_subscribe");//是否关注公众号
                    
                    //附加参数【商标申请_0bda32824db44d6f9611f1047829fa3b_15460】--【业务类型_会员ID_订单号】
                    String attach = (String)packageParams.get("attach");
                    //商户订单号
                    String out_trade_no = (String)packageParams.get("out_trade_no");  
                    //付款金额【以分为单位】
                    String total_fee = (String)packageParams.get("total_fee");
                    //账号id
                    String accountId = (String)packageParams.get("accountId");
                    //userid
                    String userId = (String)packageParams.get("userId");
                    //微信生成的交易订单号
                    String transaction_id = (String)packageParams.get("transaction_id");//微信支付订单号
                    //支付完成时间
                    String time_end=(String)packageParams.get("time_end");
                    
                    //lg.info("app_id:"+app_id);
                    //lg.info("mch_id:"+mch_id);  
                    //lg.info("openid:"+openid);  
                    //lg.info("is_subscribe:"+is_subscribe);  
                    //lg.info("out_trade_no:"+out_trade_no);  
                    //lg.info("total_fee:"+total_fee);  
                    //lg.info("额外参数_attach:"+attach); 
                    //lg.info("time_end:"+time_end); 
                    FINAccount finAccount= accountcDao.selectByPrimaryKey(accountId);
                    
                    FINIncomeDetail finIncomeDetail = new FINIncomeDetail();
                    finIncomeDetail.setFinIncomeId(out_trade_no);
                    finIncomeDetail.setFinAvailAmount(new BigDecimal(total_fee));
                    finIncomeDetail.setFinInAmount(new BigDecimal(total_fee));
                    finIncomeDetail.setFinInPayChannel(FINInoutPayChannelEnums.FINInoutPayChannel.WXPAY.getValue());
                    finIncomeDetail.setFinInWay(FINInWayEnums.FINInWay.RECHARGE.getValue());
                    finIncomeDetail.setFinInAccount(accountId);
                    finIncomeDetail.setCreateTime(DateUtil.parse(time_end,DateUtil.LONG_WEB_FORMAT));
                    finIncomeDetail.setCreateBy(userId);
                    finIncomeDetail.setDel(FINDelEnums.UDMDel.EFFECTIVE.getValue());
                    incomeDetailDao.insertSelective(finIncomeDetail);
                    
                    
                    FINAccountRlInout finAccountRlInout = new FINAccountRlInout();
                    finAccountRlInout.setFinAccountId(accountId);
                    finAccountRlInout.setFinInoutId(finIncomeDetail.getFinIncomeId());
                    finAccountRlInout.setFinInoutType(FINInoutTypeEnums.FININOUTTYPE.INCOME.getValue());
                    finAccountRlInout.setCreateTime(DateUtil.parse(time_end,DateUtil.LONG_WEB_FORMAT));
                    finAccountRlInout.setUpdateTime(DateUtil.parse(time_end,DateUtil.LONG_WEB_FORMAT));
                    finAccountRlInout.setCreateBy(userId);
                    finAccountRlInout.setUpdateBy(userId);
                    finAccountRlInout.setDel(FINDelEnums.UDMDel.EFFECTIVE.getValue());
                    accountRlInoutDao.insertSelective(finAccountRlInout);
                    
                    finAccount.setFinAvailAmount(finAccount.getFinAvailAmount().add(new BigDecimal(total_fee)));
                    finAccount.setFinTotalIncome(finAccount.getFinTotalIncome().add(new BigDecimal(total_fee)));
                    finAccount.setUpdateTime(DateUtil.parse(time_end,DateUtil.LONG_WEB_FORMAT));
                    finAccount.setUpdateBy(userId);
                   accountcDao.updateByPrimaryKeySelective(finAccount);
                    //执行自己的业务逻辑结束
                    //lg.info("支付成功");  
                    //通知微信.异步确认成功.必写.不然会一直通知后台.八次之后就认为交易失败了. 
                    
                    
                    
                    
                    resXml = "<xml>" + "<return_code><![CDATA[SUCCESS]]></return_code>"  
                            + "<return_msg><![CDATA[OK]]></return_msg>" + "</xml> ";  
                      
                } else {  
                   // lg.info("支付失败,错误信息：" + packageParams.get("err_code"));  
                    resXml = "<xml>" + "<return_code><![CDATA[FAIL]]></return_code>"  
                            + "<return_msg><![CDATA[报文为空]]></return_msg>" + "</xml> ";  
                }  
                //------------------------------  
                //处理业务完毕  
                //------------------------------  
                BufferedOutputStream out = new BufferedOutputStream(  
                        response.getOutputStream());  
                out.write(resXml.getBytes());  
                out.flush();  
                out.close();
            } else{  
                //lg.info("通知签名验证失败");  
            }  
              
        }
    
    /**
    * js循环判断微信是否支付成功
    * @param request
    * @param response
    * @throws Exception
    */
    public String isSuccess(HttpServletRequest request,HttpServletResponse response) throws Exception{
    	
    	String out_trade_no =  request.getParameter("out_trade_no");
    	if(out_trade_no == null || out_trade_no.equals("")){
    		return "0";
    	}else{
    		 FINIncomeDetail finIncomeDetail = incomeDetailDao.selectByPrimaryKey(out_trade_no);
    		 if(finIncomeDetail == null){
    			 return "0";
    		 }else{
    			 return "1";
    		 }
    		
    	}

    }
}
